package com.rockcent.wechat.helper;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.common.utils.RDigestUtils;
import com.rockcent.mall.lib.domain.Customer;
import com.rockcent.mall.lib.domain.CustomerProductOrder;
import com.rockcent.mall.lib.domain.Mall;
import com.rockcent.mall.lib.domain.CustomerCouponWallet;
import com.rockcent.mall.lib.domain.enumclass.CustomerCouponWalletStatus;
import com.rockcent.mall.lib.domain.enumclass.CustomerProductOrderStatus;
import com.rockcent.mall.lib.domain.enumclass.VerifyType;
import com.rockcent.mall.lib.dto.CustomerDto;
import com.rockcent.mall.lib.repository.CustomerCouponWalletRepository;
import com.rockcent.mall.lib.repository.CustomerProductOrderRepository;
import com.rockcent.mall.lib.repository.MallRepository;
import com.rockcent.wechat.Config;
import com.rockcent.wechat.Prop;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * Created by HK on 16/10/14.
 */
@Component
public class CustomerHelper {

    @Autowired
    private Prop prop;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private CustomerCouponWalletRepository customerCouponWalletRepository;
    @Autowired
    private CustomerProductOrderRepository customerProductOrderRepository;

    @Autowired
    private MallRepository mallRepository;

    public CustomerDto getSession(HttpServletRequest request) {
        return (CustomerDto) request.getSession().getAttribute(prop.customerLoginName);
    }

    /**
     * @param customer
     * @param request
     * @param response
     * @param source
     * @return
     * @throws JsonProcessingException
     */
    public CustomerDto setSession(Customer customer, HttpServletRequest request, HttpServletResponse response, String source) throws JsonProcessingException {
        // 包装用户信息
        String openId = "";
        String wechatOpenId = customer.getWechatOpenId();
        String wxappOpenId = customer.getWxappOpenId();
        if ("WXAPP".equals(source)) {
            openId = wxappOpenId;
        } else if ("WEIXIN".equals(source)) {
            openId = wechatOpenId;
        }
        String userToken = DigestUtils.md5Hex(openId + new Date().getTime());

        // 把C端用户的 token存放到redis
        String sessionId = Customer.REDIS_CUSTOMER_USER_TOKEN_PREFIX + userToken;
        stringRedisTemplate.opsForValue().set(sessionId, String.valueOf(customer.getId()));


        if (prop.env.equals(Config.DEV)) {
            stringRedisTemplate.expire(sessionId, 30, TimeUnit.DAYS);// 开发环境session 30天，便于开发测试
        } else {
            stringRedisTemplate.expire(sessionId, 119, TimeUnit.MINUTES);// 默认119分钟有效,由于微信accessToken两小时有效期
        }


        CustomerDto customerDto = (CustomerDto) request.getSession().getAttribute(prop.customerLoginName);
        customerDto.setId(customer.getId());
        customerDto.setUserToken(userToken);
        customerDto.setIsBindingMobile(Whether.NO.toString());
        customerDto.setWechatOpenId(wechatOpenId);
        customerDto.setWxappOpenId(wxappOpenId);
//        customerDto.setNickName(customer.getNickName());
        customerDto.setSessionId(sessionId);
        customerDto.setMobile(customer.getMobile());
        if (StringUtils.isNotBlank(customer.getMobile())) {
            customerDto.setIsBindingMobile(Whether.YES.toString());
        }
        Mall mall = mallRepository.findOne(customerDto.getMallId());
        customerDto.setMallName(mall.getName());
        // 设置到浏览器的cookie
        Cookie cookie = new Cookie(prop.cookieCustomerName, objectMapper.writeValueAsString(customerDto));
        cookie.setMaxAge(7100); // 默认119分钟有效,由于微信accessToken两小时有效期
        cookie.setPath("/");
        cookie.setDomain(prop.cookieFirstDomain);
        response.addCookie(cookie);

        // 设置session
        request.getSession().setAttribute(prop.customerLoginName, customerDto);
        return customerDto;
    }

    public CustomerDto setSession(Customer customer, HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException {
        return setSession(customer, request, response, "WEIXIN");
    }

    /**
     * 生成渠道分销码
     *
     * @return
     */
    public String genShareCode() {
        return RDigestUtils.md5Hex(new Date().getTime() + new Random().nextInt() + "");
    }

    /**
     * 生成核销唯一辨识码
     *
     * @param merchantId 商家ID
     * @param customerId 用户ID
     * @param couponId   卡卷ID
     * @param verifyCode 兑换码
     * @return
     */
    public String customerCouponCodeMd5(Long merchantId, Long customerId, Long couponId, Integer verifyCode) {
        StringBuilder sb = new StringBuilder();
        sb.append(merchantId).append(customerId).append(couponId).append(verifyCode).append(new Date().getTime());
        return RDigestUtils.md5Hex(sb.toString());
    }

    /**
     * 生成用户卡卷兑换码
     *
     * @return
     */
    public Integer verifyCode(VerifyType verifyType) {
        Integer verifyCode = new Random().nextInt(89999999) + 10000000;
        if (VerifyType.COUPON == verifyType) {
            CustomerCouponWallet couponWallet = customerCouponWalletRepository.findByVerifyCodeAndStatusAndIsDelete(String.valueOf(verifyCode), CustomerCouponWalletStatus.TO_USE, Whether.NO);
            if (couponWallet != null) {
                this.verifyCode(verifyType);
            }
        }
        if (VerifyType.ORDER == verifyType) {
            CustomerProductOrder productOrder = customerProductOrderRepository.findByVerifyCodeAndStatusAndIsDelete(String.valueOf(verifyCode), CustomerProductOrderStatus.TO_USE, Whether.NO);
            if (productOrder != null) {
                this.verifyCode(verifyType);
            }
        }

        return verifyCode;
    }

    public String customerGiftCodeMd5(String giftId, Long id, String mallOrderNum, Integer verifyCode) {

        StringBuilder sb = new StringBuilder();
        sb.append(giftId).append(id.longValue()).append(mallOrderNum).append(verifyCode).append(new Date().getTime());
        return RDigestUtils.md5Hex(sb.toString());
    }
}
